<template>
  <div class="graph_box">
    <div style="padding: 10px ;text-align: center;">
      <el-radio-group v-model="viewModeBefore" @change="switchViewMode">
        <el-radio-button label="graph">关系图谱</el-radio-button>
        <el-radio-button label="mindmap">思维导图</el-radio-button>
      </el-radio-group>
    </div>
    <div ref="graphRef" class="graph_ref" />
  </div>
</template>
<script lang="ts">
import * as echarts from 'echarts/core'
import { GraphChart, GraphSeriesOption, TreeChart, TreeSeriesOption } from 'echarts/charts'
import { TitleComponent, TitleComponentOption, TooltipComponent, TooltipComponentOption, LegendComponent, LegendComponentOption } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'

// 注册必需的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  LegendComponent,
  GraphChart,
  TreeChart,
  CanvasRenderer
])


// 添加视图模式类型

export default {
  name: 'Knowledge',
  props: {
    graphData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      viewModeBefore: 'graph',
      viewMode: 'graph',
      isTransitioning: false,
      chart: null
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart()
      window.addEventListener('resize', this.handleResize)
    })
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize)
    this.chart.dispose()
  },
  watch: {
    graphData: {
      handler() {
        this.$nextTick(() => {
          if (this.chart) {
            this.chart.setOption({
              series: [{
                data: this.graphData.nodes.map(node => ({
                  ...node,
                  name: node.label,
                  symbolSize: 70,
                  value: node.description
                })),
                links: this.graphData.links.map(link => ({
                  ...link,
                  symbolSize: [8, 12],
                  symbol: ['circle', 'arrow'],
                  lineStyle: {
                    width: 2,
                    curveness: 0.2,
                    color: '#A0AEC0'
                  },
                  label: {
                    show: true,
                    formatter: ({ data }) => this.truncateText(data.relation),
                    fontSize: 12,
                    color: '#4A5568',
                    backgroundColor: 'rgba(255, 255, 255, 0.8)',
                    padding: [4, 8],
                    borderRadius: 4,
                    position: 'middle'
                  }
                }))
              }]
            })
          }
        })
      },
      deep: true
    }
  },
  methods: {
    switchViewMode(mode) {
      if (this.viewMode == mode || this.isTransitioning) return
      this.isTransitioning = true
      this.viewMode = mode
      this.$nextTick(() => {
        this.initChart()
        setTimeout(() => {
          this.isTransitioning = false
        }, 500)
      })
    },
    truncateText(text, maxLength = 8) {
      return text.length > maxLength ? text.slice(0, maxLength) + '...' : text
    },
    initChart() {
      const graphRef = this.$refs.graphRef
      if (!graphRef) return
      this.chart = echarts.init(graphRef)
      const option = this.viewMode === 'graph' ? this.getGraphOption() : this.getMindMapOption()
      this.chart.setOption(option)
    },
    getGraphOption() {
      return {
        title: {
          show: false,
          text: '关系图谱',
          subtext: '',
          top: 20,
          left: 'center',
          textStyle: {
            fontSize: 28,
            fontWeight: 'bold',
            color: '#2D3748'
          },
          subtextStyle: {
            fontSize: 16,
            color: '#4A5568'
          }
        },
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(255, 255, 255, 0.95)',
          borderColor: '#E2E8F0',
          borderWidth: 1,
          padding: [10, 15],
          textStyle: {
            color: '#1A202C'
          },
          formatter: (params) => {
            if (params.dataType === 'node') {
              return `
                <div class="font-bold text-lg mb-1">${params.data.name}</div>
                <div class="text-gray-600">${params.data.value || ''}</div>
              `
            }
            return `
              <div class="flex items-center gap-2">
                <span class="font-bold">${params.data.source}</span>
                <span class="text-gray-400">→</span>
                <span class="font-bold">${params.data.target}</span>
              </div>
              <div class="text-gray-600 mt-2 text-sm">${params.data.relation}</div>
            `
          }
        },
        legend: {
          data: ['基础理论', '临床应用', '技术设备', '图像解读'],
          orient: 'vertical',
          right: 50,
          top: 'middle',
          textStyle: {
            fontSize: 14,
            color: '#4A5568'
          },
          itemGap: 20,
          itemWidth: 24,
          itemHeight: 14,
          borderWidth: 1,
          borderColor: '#E2E8F0',
          padding: 20,
          backgroundColor: 'rgba(255, 255, 255, 0.8)',
          show: false,
        },
        animationDurationUpdate: 1500,
        animationEasingUpdate: 'quinticInOut',
        series: [{
          type: 'graph',
          layout: 'force',
          data: this.graphData.nodes.map(node => ({
            ...node,
            name: node.label,
            symbolSize: 70,
            value: node.description,
            itemStyle: {
              borderWidth: 3,
              borderColor: '#fff',
              shadowBlur: 15,
              shadowColor: 'rgba(0, 0, 0, 0.2)',
              color: {
                type: 'radial',
                x: 0.5,
                y: 0.5,
                r: 0.5,
                colorStops: [{
                  offset: 0,
                  color: this.getCategoryColor(node.category, 0.9)
                }, {
                  offset: 1,
                  color: this.getCategoryColor(node.category, 0.7)
                }]
              }
            },
            label: {
              show: true,
              position: 'right',
              distance: 5,
              fontSize: 14,
              fontWeight: 'bold',
              color: '#2D3748',
              backgroundColor: 'rgba(255, 255, 255, 0.8)',
              padding: [4, 8],
              borderRadius: 4
            }
          })),
          links: this.graphData.links.map(link => ({
            ...link,
            symbolSize: [8, 12],
            symbol: ['circle', 'arrow'],
            lineStyle: {
              width: 2,
              curveness: 0.2,
              color: '#A0AEC0',
              type: 'solid'
            },
            label: {
              show: true,
              formatter: ({ data }) => this.truncateText(data.relation),
              fontSize: 12,
              color: '#4A5568',
              backgroundColor: 'rgba(255, 255, 255, 0.8)',
              padding: [4, 8],
              borderRadius: 4,
              position: 'middle',
              rich: {
                time: {
                  fontSize: 12,
                  color: '#999'
                }
              }
            }
          })),
          categories: [
            { name: '基础理论', itemStyle: { color: '#3B82F6' } },
            { name: '临床应用', itemStyle: { color: '#8B5CF6' } },
            { name: '质量控制', itemStyle: { color: '#10B981' } },
            { name: '技术设备', itemStyle: { color: '#F59E0B' } },
            { name: '图像解读', itemStyle: { color: '#EC4899' } }
          ],
          roam: true,
          draggable: true,
          focus: 'adjacency',
          force: {
            repulsion: 300,
            edgeLength: 200,
            gravity: 0.1,
            friction: 0.6
          },
          emphasis: {
            focus: 'adjacency',
            scale: true,
            lineStyle: {
              width: 4
            },
            label: {
              fontSize: 16,
              fontWeight: 'bold'
            }
          }
        }]
      }
    },
    getMindMapOption() {
      return {
        title: {
          show: false,

          text: '思维导图',
          subtext: '',
          top: 20,
          left: 'center',
          textStyle: {
            fontSize: 28,
            fontWeight: 'bold',
            color: '#2D3748',
            fontFamily: '"Inter", sans-serif'
          },
          subtextStyle: {
            fontSize: 16,
            color: '#4A5568',
            fontFamily: '"Inter", sans-serif'
          }
        },
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(255, 255, 255, 0.98)',
          borderColor: '#E2E8F0',
          borderWidth: 1,
          padding: [12, 16],
          borderRadius: 8,
          textStyle: {
            color: '#1A202C',
            fontSize: 14
          },
          formatter: (params) => {
            return `
              <div style="font-weight: 600; font-size: 16px; margin-bottom: 8px;">
                ${params.data.name}
              </div>
              <div style="color: #4A5568; line-height: 1.5;">
                ${params.data.value || ''}
              </div>
              ${params.data.category ? `
                <div style="margin-top: 8px; padding: 4px 8px; background: ${this.getCategoryColor(params.data.category, 0.1)}; 
                     color: ${this.getCategoryColor(params.data.category, 1)}; border-radius: 4px; font-size: 12px;">
                  ${params.data.category}
                </div>
              ` : ''}
            `
          }
        },
        series: [{
          type: 'tree',
          data: [this.transformToTreeData()],
          top: '15%',
          bottom: '15%',
          left: '10%',
          right: '20%',
          layout: 'orthogonal',
          orient: 'LR',
          initialTreeDepth: -1,
          symbolSize: 16,
          symbol: 'circle',
          edgeShape: 'polyline',
          expandAndCollapse: true,
          label: {
            show: true,
            position: 'right',
            distance: 10,
            fontSize: 14,
            color: '#2D3748',
            fontFamily: '"Inter", sans-serif',
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            padding: [6, 12],
            borderRadius: 6,
            formatter: (params) => {
              const value = params.data
              return [
                `{name|${value.name}}`,
                value.category ? `{category|${value.category}}` : ''
              ].filter(Boolean).join('\n')
            },
            rich: {
              name: {
                fontSize: 14,
                fontWeight: 500,
                color: '#2D3748',
                lineHeight: 20
              },
              category: {
                fontSize: 12,
                color: '#6B7280',
                backgroundColor: 'rgba(0,0,0,0.04)',
                padding: [2, 6],
                borderRadius: 4,
                lineHeight: 16
              }
            }
          },
          leaves: {
            label: {
              position: 'right',
              distance: 10,
              verticalAlign: 'middle'
            }
          },
          itemStyle: {
            borderWidth: 2,
            borderColor: '#fff',
            shadowBlur: 12,
            shadowColor: 'rgba(0, 0, 0, 0.1)',
            color: (params) => {
              const color = this.getCategoryColor(params.data.category, 0.9)
              return new echarts.graphic.LinearGradient(0, 0, 1, 1, [
                { offset: 0, color: color },
                { offset: 1, color: this.getCategoryColor(params.data.category, 0.7) }
              ])
            }
          },
          lineStyle: {
            color: '#CBD5E1',
            width: 1.5,
            curveness: 0.5
          },
          emphasis: {
            focus: 'descendant',
            itemStyle: {
              shadowBlur: 20,
              shadowColor: 'rgba(0, 0, 0, 0.2)'
            },
            lineStyle: {
              width: 2,
              shadowBlur: 8,
              shadowColor: 'rgba(0, 0, 0, 0.2)'
            },
            label: {
              fontSize: 16,
              backgroundColor: 'rgba(255, 255, 255, 0.95)',
              shadowBlur: 12,
              shadowColor: 'rgba(0, 0, 0, 0.1)'
            }
          },
          animationDuration: 500,
          animationEasing: 'cubicOut',
          animationDelay: (idx) => idx * 100
        }]
      }
    },
    transformToTreeData() {
      const rootNode = this.graphData.nodes[0]
      if (!rootNode) return {}
      const nodeMap = new Map()
      this.graphData.nodes.forEach(node => nodeMap.set(node.id, { ...node, children: [] }))
      this.graphData.links.forEach(link => {
        const sourceNode = nodeMap.get(link.source)
        const targetNode = nodeMap.get(link.target)
        if (sourceNode && targetNode) {
          sourceNode.children.push({
            ...targetNode,
            relation: link.relation
          })
        }
      })
      const buildNode = (node) => {
        return {
          name: node.label,
          value: node.description,
          category: node.category,
          relation: node.relation,
          children: node.children.length > 0 ? node.children.map(buildNode) : undefined,
          itemStyle: {
            color: this.getCategoryColor(node.category, 0.9)
          },
          lineStyle: node.relation ? {
            color: '#94A3B8',
            label: {
              show: true,
              formatter: this.truncateText(node.relation),
              fontSize: 12,
              color: '#64748B',
              backgroundColor: 'rgba(255, 255, 255, 0.9)',
              padding: [2, 6],
              borderRadius: 4
            }
          } : undefined
        }
      }
      return buildNode(nodeMap.get(rootNode.id))
    },
    getCategoryColor(category, alpha = 1) {
      const colorMap = {
        '基础理论': `rgba(59, 130, 246, ${alpha})`,
        '临床应用': `rgba(139, 92, 246, ${alpha})`,
        '质量控制': `rgba(16, 185, 129, ${alpha})`,
        '技术设备': `rgba(245, 158, 11, ${alpha})`,
        '图像解读': `rgba(236, 72, 153, ${alpha})`
      }
      return colorMap[category] || colorMap['基础理论']
    },
    handleResize() {
      this.chart.resize()
    }
  }
}
</script>

<style scoped>
.graph_box {
  width: 100%;
  height: 100%;
}

.graph_ref {
  width: 100%;
  height: calc(100% - 60px);
}
</style>